package com.tqjc.system.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tqjc.system.common.constant.ConfigConstant;
import com.tqjc.system.common.constant.GlobalConstant;
import com.tqjc.system.common.constant.RemoteURLConstant;
import com.tqjc.system.common.entity.BO.PLCWriteRequestParamBO;
import com.tqjc.system.common.entity.BO.ResponseLabelDataBO;
import com.tqjc.system.system.util.SystemUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author 86195
 * @version 1.0
 * @description 请求工具类
 * @date 2023/10/19 14:15
 */
@Slf4j
public class HttpsUtils {

    private static String TMS_SOURCE_APP_CODE_VAL = "FG";

    private static String TMS_SERVICEID_VAL = "FGTQ01";

    private static String CONNECTION_VAL = "keep-alive";

    private static CloseableHttpClient httpClient;


    static {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        //设置整个连接池最大连接数
        connectionManager.setMaxTotal(400);

        //路由是对maxTotal的细分
        connectionManager.setDefaultMaxPerRoute(300);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)  //返回数据的超时时间
                .setConnectTimeout(10000) //连接上服务器的超时时间
                .setConnectionRequestTimeout(1000) //从连接池中获取连接的超时时间
                .build();
        CloseableHttpClient client = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
        httpClient =  client;

    }

    /**
     * 设置超时时间
     */
    private static RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(5000)
            .setConnectTimeout(5000).setSocketTimeout(5000).build();


    public static <T> T sendPost(String url,String paramJson,Class<T> t) throws IOException {
        T res = null;
        CloseableHttpResponse response = null;
        HttpPost httpPost = new HttpPost(url);
        try {
            httpPost.setEntity(new StringEntity(paramJson,"utf-8"));
            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity(), "utf-8");
            res= JSONObject.parseObject(s, t);

        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendPost running error,响应参数转换异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
            response.close();
        }
        return res;

    }


    public static <T> T sendParamsPost(String url,String paramLable,String paramValue, Class<T> t) throws IOException, URISyntaxException {
        T res = null;
        CloseableHttpResponse response = null;
        try {
            // 创建URI，并添加参数
            URI uri = new URIBuilder(url)
                    .addParameter(paramLable, paramValue)
                    .build();
            HttpPost httpPost = new HttpPost(uri);
//            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.addHeader("Accept","*/*");
//            httpPost.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity(), "utf-8");
            res= JSONObject.parseObject(s, t);

        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendParamsPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendParamsPost running error,响应参数转换异常",e);
            throw e;
        } catch (URISyntaxException e) {
            log.error("HttpsUtils sendParamsPost running error,URI路径参数异常",e);
            throw e;
        } finally {
            response.close();
        }
        return res;

    }


    public static void sendTMSPost(String url,String paramJson) throws Exception {
        CloseableHttpResponse response = null;

        HttpPost httpPost = new HttpPost(url);
        try {
            httpPost.setEntity(new StringEntity(paramJson,"utf-8"));
            httpPost.addHeader("sourceAppCode",TMS_SOURCE_APP_CODE_VAL);
            httpPost.addHeader("password","");
            httpPost.addHeader("serviceId",TMS_SERVICEID_VAL);
            httpPost.addHeader("msgSendTime",DateUtils.formatDateByPattern(new Date(),"yyyyMMddHHmmssSSS"));
            httpPost.addHeader("Content-Type","application/json");
            httpPost.addHeader("Connection",TMS_SOURCE_APP_CODE_VAL);
            httpPost.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity(), "utf-8");

        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendPost running error,响应参数转换异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
            response.close();
        }
    }


    public static void sendPost(String url,String paramJson) throws IOException {
        CloseableHttpResponse response = null;

        HttpPost httpPost = new HttpPost(url);
        try {
            httpPost.setEntity(new StringEntity(paramJson,"utf-8"));
            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpPost);
            String s = EntityUtils.toString(response.getEntity(), "utf-8");

        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendPost running error,响应参数转换异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
            response.close();
        }

    }


    public static void sendPost(String url) throws IOException {
        CloseableHttpResponse response = null;

        HttpPost httpPost = new HttpPost(url);
        try {
            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpPost);
        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendPost running error,响应参数转换异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
            response.close();
        }

    }



    public static void sendGet(String url) throws IOException {
        CloseableHttpResponse response = null;

        HttpGet httpGet = new HttpGet(url);
        try {
            httpGet.addHeader("Content-Type","application/json;charset=utf-8");
            httpGet.setConfig(config);
            response = (CloseableHttpResponse) httpClient.execute(httpGet);
        } catch (UnsupportedEncodingException e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } catch (IOException e){
            log.error("HttpsUtils sendPost running error,响应参数转换异常",e);
            throw e;
        } finally {
            httpGet.releaseConnection();
            response.close();
        }

    }


    public static void writeMoreVal(String url,PLCWriteRequestParamBO paramBO,HttpClient client) throws Exception {


        HttpPost httpPost = new HttpPost(url);
        try {
            String paramJson = paramBO.getParamJSONString();
            httpPost.setEntity(new StringEntity(paramJson,"utf-8"));
            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.setConfig(config);
            httpClient.execute(httpPost);

        } catch (Exception e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
        }


    }


    public static void write(String url, PLCWriteRequestParamBO paramBO) throws Exception {

        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;
        try {
            String paramJson = paramBO.getParamJSONString();
            httpPost.setEntity(new StringEntity(paramJson,"utf-8"));
            httpPost.addHeader("Content-Type","application/json;charset=utf-8");
            httpPost.setConfig(config);
            int i = 0;
            while (true){
                //写操作
                response = (CloseableHttpResponse) httpClient.execute(httpPost);
                Thread.sleep(300);
                //读值操作
                Map<String,String> paramMap = new HashMap(2);
                Map<String, String> snMap = SystemUtils.Sys_carInfo.get(ConfigConstant.CONFIG_TYPE_CAR_BAK_SN);
                String sn = snMap.get(paramBO.getMacSN());
                paramMap.put(GlobalConstant.STRING_LABEL,paramBO.getLabel());
                paramMap.put(GlobalConstant.STRING_SN,sn);
                ResponseLabelDataBO res = HttpsUtils.sendPost(RemoteURLConstant.URL_READBC, JSON.toJSONString(paramMap), ResponseLabelDataBO.class);
                Map<String, String> content = res != null? res.getContent(): null;
                if(content != null){
                    String currentVal = content.get("currentVal") != null ?
                            content.get("currentVal").toLowerCase() : null;
                    if(Objects.equals(currentVal,paramBO.getValue())){
                        //标定完成后，跳出循环
                        break;
                    }
                }
                i++;
                if(i > 3){
                    throw new Exception("写值操作超过三次");
                }
            }


        } catch (Exception e){
            log.error("HttpsUtils sendPost running error,接口调用异常",e);
            throw e;
        } finally {
            httpPost.releaseConnection();
            response.close();
        }


    }


    public static boolean valIsSuccess(String sn,String label,String targetVal) throws IOException {
        Map<String,String> paramMap = new HashMap(2);
        paramMap.put(GlobalConstant.STRING_LABEL,label);
        paramMap.put(GlobalConstant.STRING_SN,sn);
        ResponseLabelDataBO res = HttpsUtils.sendPost(RemoteURLConstant.URL_READBC, JSON.toJSONString(paramMap), ResponseLabelDataBO.class);
        Map<String, String> content = res != null? res.getContent(): null;
        if(content != null){
            String currentVal = content.get("currentVal") != null ?
                    content.get("currentVal").toLowerCase() : null;
            if(Objects.equals(currentVal,targetVal)){
                return true;
            }
        }

        return false;

    }
}
